﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "EditComponentTypeDlg.h"
#include "AddNewFamilyTypeDlg.h"
#include "IDocument.h"
#include "IFamily.h"
#include "IFamilyType.h"
#include "IElementBasicInformation.h"
#include "IElementParameters.h"
#include "GbmpBuiltInParameterDefinitions.h"
#include "GmStyleSheetHelper.h"
#include "IGenericType.h"
#include "IParameter.h"
#include "IParameterDefinition.h"
#include "IParameterDefinitionLibrary.h"
#include "IParameterDisplayCheckbox.h"
#include "IParameterDisplayDropdownList.h"
#include "IParameterDisplayEditbox.h"
#include "IParameterDisplayEditboxWithButton.h"
#include "IInstanceType.h"
#include "IUserTransaction.h"
#include "UniIdentity.h"
#include "IParameterDefinition.h"
#include "ParameterDisplayUtils.h"
#include "IParameterGroupsFilter.h"
#include "PropertyInstanceSetting.h"
#include "PropertyInstanceWidget.h"
#include "UiCommonDialog.h"
#include "ParameterType.h"
#include "IParameterDisplayManager.h"
#include "IDrawingViewportType.h"
#include "IGraphicsMaterial.h"
#include "IElement.h"
#include "IParameterValueStorage.h"
#include "IGraphicsMaterialData.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;
using namespace PropertyWidget;


EditComponentTypeDlg::EditComponentTypeDlg(gcmp::IDocument*pDoc, const gcmp::ElementId& typeId, QWidget *parent /* = 0 */)
    :QDialog(parent, Qt::FramelessWindowHint)
    , m_pDoc(pDoc)
    , m_typeId(typeId)
    , m_pInstaceWidget(nullptr)
{
    m_ui.setupUi(this);
    setFixedSize(336, 371);

    // Style
    std::wstring styleSheetStr = GmStyleSheetHelper::Instance()->GetCurrentStyleData();
    setStyleSheet(QString::fromStdWString(styleSheetStr));

    // Title
    m_ui.gbmp_title->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
    m_ui.gbmp_title->setIconVisible(false);
    m_ui.gbmp_title->setMaxButtonVisible(false);
    m_ui.gbmp_title->setMinButtonVisible(false);
    m_ui.gbmp_title->setText(QString::fromStdWString(GBMP_TR(L"类型参数")));
    m_ui.pushButton_Ok->setObjectName(QStringLiteral("EditComponentTypeDlg_pushButton_Ok"));
    m_ui.pushButton_Cancel->setObjectName(QStringLiteral("EditComponentTypeDlg_pushButton_Cancel"));
    this->setProperty("use_gbmp_title", true);
    // type name
    IType* pType = quick_cast<IType>(m_pDoc->GetElement(m_typeId));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pType, L"pType不能为空",L"GDMPLab",L"2024-03-30");
    const std::wstring typeName = pType->GetBasicInformation()->GetName();
    m_ui.lineEdit_TypeName->setText(QString::fromStdWString(typeName));

    connect(m_ui.gbmp_title, &GmTitleBar::closeRequested, this, &EditComponentTypeDlg::reject);
    connect(m_ui.gbmp_title, &GmTitleBar::moveRequested, this, &EditComponentTypeDlg::onMoveRequested);
    connect(m_ui.pushButton_Ok, SIGNAL(clicked()), this, SLOT(ClickOkButton()));
    connect(m_ui.pushButton_Cancel, SIGNAL(clicked()), this, SLOT(ClickCancelButton()));
    
    bool canRename = true;
    IElementParameters* pElementParameter = pType->GetElementParameters();
    if (pElementParameter)
    {
        IParameterDefinitionLibrary* pParamDefLib = IParameterDefinitionLibrary::Get(pDoc);
        if (pParamDefLib && !pElementParameter->IsParameterModifiable(pParamDefLib->GetParameterDefinitionIdByUid(PARAMETER_UID(ElementNameBuiltInParameter))))
        {
            m_ui.pushButton_Rename->setDisabled(true);
        }
    }
    connect(m_ui.pushButton_Rename, SIGNAL(clicked()), this, SLOT(ClickRenameButton()));

    UpdateParameterOnTable();
}

EditComponentTypeDlg::~EditComponentTypeDlg()
{
    m_vecDisplayedParameters.clear();
}

QString EditComponentTypeDlg::TypeName() const
{
    return m_ui.lineEdit_TypeName->text();
}

void EditComponentTypeDlg::setTypeName(const QString &name)
{
    m_ui.lineEdit_TypeName->setText(name);
}

void EditComponentTypeDlg::onMoveRequested(const QPoint& cursorPos, const QPoint& offset)
{
    Q_UNUSED(cursorPos);
    move(pos() + offset);
}

void EditComponentTypeDlg::ClickOkButton()
{
    OwnerPtr<IUserTransaction> ut = IUserTransaction::Create(m_pDoc, GBMP_TR(L"修改构件属性"), true);
    // 从列表界面修改类型参数更新到Element（提交事务)
    UpdatePropertyTableToElement();
   ut->Commit();

    QDialog::accept();
}

void EditComponentTypeDlg::ClickCancelButton()
{
    QDialog::reject();
}

void EditComponentTypeDlg::ClickRenameButton()
{
    IType* pType = quick_cast<IType>(m_pDoc->GetElement(m_typeId)) ;
    DBG_WARN_AND_RETURN_VOID_UNLESS(pType, L"pType不能为空",L"GDMPLab",L"2024-03-30");

    // 必须指定父类是当前对话框
    AddNewFamilyTypeDlg* pDlg = NEW_AS_QT_CHILD(AddNewFamilyTypeDlg, m_pDoc, pType, this);
    int rt = pDlg->exec();
}

void EditComponentTypeDlg::OnPropertyValueChanged(int groupIndex, int propertyIndex)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pInstaceWidget != nullptr, L"m_pInstaceWidget为空",L"GDMPLab",L"2024-03-30");
    CPropertyItem* pItem = m_pInstaceWidget->GetPropertyByIndex(groupIndex, propertyIndex);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pItem != nullptr, L"pItem为空",L"GDMPLab",L"2024-03-30");
    IElement* pickedElement = m_pDoc->GetElement(m_typeId);
    if (!pickedElement || !pickedElement->GetElementParameters())
        return;
    OwnerPtr<IParameter> currentParam = 
        pickedElement->GetElementParameters()->GetParameterById(pItem->UniqueID());
    DBG_WARN_AND_RETURN_VOID_UNLESS(IParameter::IsValidParameter(currentParam), L"Parameter获取不到",L"GDMPLab",L"2024-03-30");
    const IParameterDefinition* currentParamDef = currentParam->GetParameterDefinition();
    DBG_WARN_AND_RETURN_VOID_UNLESS(currentParamDef, L"ParameterDefinition获取不到",L"GDMPLab",L"2024-03-30");
    IParameterDisplayManager* pParamDisplayMgr = IParameterDisplayManager::Get(m_pDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pParamDisplayMgr, L"pParamDisplayMgr为空",L"GDMPLab",L"2024-03-30");
    const IParameterDisplay* paramDisplay = pParamDisplayMgr->GetParameterDisplay(currentParamDef);
    if (const IParameterDisplayDropdownList* dropdownList = dynamic_cast<const IParameterDisplayDropdownList*>(paramDisplay))
    {
        QString strCurValue = pItem->GetValue().toString();
        std::vector<ElementId> ids = { m_typeId };
        OwnerPtr<IParameterValueStorage> pvs = dropdownList->GetValueByDisplayString(m_pDoc, strCurValue.toStdWString(), ids);
        if (!pvs)
        {
            if (strCurValue.compare(QString::fromStdWString(L"更多材质")) == 0)
            {
                OwnerPtr<IUserTransaction> ut = IUserTransaction::Create(m_pDoc, GBMP_TR(L"修改构件属性"));
                ElementId materialId;
                UiCommonDialog::ShowMaterialSelectionDialog(m_pDoc, materialId);
                if (!materialId.IsValid())
                {
                    return;
                }

                IGraphicsMaterial* pMaterialElement = quick_cast<IGraphicsMaterial>(m_pDoc->GetElement(materialId));
                if (pMaterialElement == nullptr)
                {
                    UiCommonDialog::ShowMessageBox(GBMP_TR(L"发生错误"), GBMP_TR(L"材质创建失败！"), (int)UiCommonDialog::ButtonType::OK);
                    return;
                }
                OwnerPtr<IGraphicsMaterialData> pData = pMaterialElement->GetGraphicsMaterialDataFromMaterialInstance();
                DBG_WARN_AND_RETURN_VOID_UNLESS(pData != nullptr, L"MaterialData获取不到",L"GDMPLab",L"2024-03-30");
                currentParam->SetValueAsElementId(materialId);
               ut->Commit();
                DisplayParameterInItem(pItem, currentParam.get(), currentParamDef);
                m_pInstaceWidget->RefreshView();
            }
        }
    }
}

void EditComponentTypeDlg::UpdateParameterOnTable()
{
    // 获取参数
    IElement* pickedElement = m_pDoc->GetElement(m_typeId);
    if (pickedElement == nullptr)
        return;    

    // 获取参数
    std::vector<OwnerPtr<IParameter>> allParams;
    if(pickedElement->GetElementParameters())
        allParams = pickedElement->GetElementParameters()->GetAllParameters();

    // 获取参数显示方式
    std::vector<const IParameterDefinition*> displayedParameterDefs;
    for (auto& eachParam : allParams)
    {
        const IParameterDefinition* paramDef = eachParam->GetParameterDefinition();
        DBG_WARN_AND_CONTINUE_UNLESS(paramDef, L"paramDef为空",L"GDMPLab",L"2024-03-30");
        const UniIdentity &uid = paramDef->GetUid();
        if (uid.HasSameValue(PARAMETER_UID(RailingAllStructureDataBuiltInParameter))   // 暂时隐藏栏杆扶手样式
            || uid.HasSameValue(PARAMETER_UID(ElementNameBuiltInParameter))            // “名称”参数不显示
            || paramDef->GetParameterTypeId() == PARAMETER_TYPE(None))
        {
            continue;
        }
        displayedParameterDefs.push_back(paramDef);
        m_vecDisplayedParameters.push_back(TransferOwnership(eachParam));
    }

    // 获取参数所在组别名称，并排序
    const IParameterGroupsFilter* pGroupsFilter = IParameterGroupsFilter::GetParameterGroupsFilter();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pGroupsFilter != nullptr, L"pGroupsFilter为空",L"GDMPLab",L"2024-03-30");
    std::unordered_set<std::wstring> unorderGroupNames;
    FOR_EACH(paramDef, displayedParameterDefs)
    {
        std::wstring groupName = pGroupsFilter->GetGroupName(paramDef);
        unorderGroupNames.emplace(groupName);
    }
    std::vector<std::wstring> allGroupNames(unorderGroupNames.begin(), unorderGroupNames.end());
    std::vector<size_t> groupsOrder = pGroupsFilter->SortGroups(allGroupNames);                     //组别排序
    m_vecParametersOrder = pGroupsFilter->SortParameters(displayedParameterDefs);                   //参数排序

    m_pInstaceWidget = CreateInstancePropertyWidget();
    // 对话框中创建参数组
    std::wstring strDefaultGroup = GBMP_TR(L"基本属性");
    std::wstring strUndefinedGroup = GBMP_TR(L"参数列表");      // 未分组的参数放在这个组下
    if (allGroupNames.size() == 1 && allGroupNames.at(0) == strDefaultGroup)
    {
        CPropertyGroupItem* pGroupItem = m_pInstaceWidget->AddPropertyGroup(-1, QString::fromStdWString(strUndefinedGroup), QString::fromStdWString(strUndefinedGroup));
        DBG_WARN_AND_RETURN_VOID_UNLESS(pGroupItem != nullptr, L"GroupItem创建不成功",L"GDMPLab",L"2024-03-30");
    }
    else
    {
        int groupId = 0;
        FOR_EACH_INDEX(idx, allGroupNames)
        {
            //注意：groupId < 0 ,(控件内部只用一个容器存放，防止与属性项ID重叠)
            QString str = QString::fromStdWString(allGroupNames.at(groupsOrder.at(idx)));
            CPropertyGroupItem* pGroupItem = m_pInstaceWidget->AddPropertyGroup(--groupId, str, str);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pGroupItem != nullptr, L"GroupItem创建不成功",L"GDMPLab",L"2024-03-30");
        }
    }

    // 把类型参数添加到所属的组别中
    for (int loop = 0; loop < (int)displayedParameterDefs.size(); ++loop)
    {
        const IParameterDefinition* paramDefinition = displayedParameterDefs.at(m_vecParametersOrder.at(loop));
        DBG_WARN_AND_CONTINUE_UNLESS(paramDefinition, L"paramDefinition为空",L"GDMPLab",L"2024-03-30");

        IParameter* currentParam = m_vecDisplayedParameters.at(m_vecParametersOrder.at(loop)).get();
        DBG_WARN_AND_CONTINUE_UNLESS(currentParam, L"currentParam为空",L"GDMPLab",L"2024-03-30");
        if (!currentParam->IsUserVisible())
        {
            continue;
        }
        // 临时代码开始：材料库分类标识
        //if (paramDefinition->GetName() == Family::GetComponentCategoryParameterName())
        //{
        //    continue;
        //}

        std::wstring groupName = pGroupsFilter->GetGroupName(paramDefinition);
        if (groupName == strDefaultGroup)
            groupName = strUndefinedGroup;

        CPropertyGroupItem* pGroupItem = m_pInstaceWidget->GetPropertyGroupByName(QString::fromStdWString(groupName));
        if (nullptr == pGroupItem)
            continue;
        
        CPropertyItem* pItem = m_pInstaceWidget->AddProperty(
            pGroupItem->GetGroupIndex()
            , paramDefinition->GetId()
            , QString::fromStdWString(paramDefinition->GetName())
            , QString::fromStdWString(paramDefinition->GetDescription())
            , QString::fromStdWString(ParameterDisplayUtils::GetValueAsDisplayString(currentParam))
            , true, esLineEdit, false);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pItem != nullptr, L"CPropertyItem添加失败",L"GDMPLab",L"2024-03-30");

        // 目前对于参数是否可修改的校验规则如下：
        // 对于ParameterProcessType::GeneralOutput型和ParameterProcessType::Bound型的参数，直接认为该参数不可修改，不采用用户自定义behavior返回的可修改性判断。
        // 对于非ParameterProcessType::GeneralOutput型和非ParameterProcessType::Bound型的参数，再进一步获取用户设定的是否可修改的属性。
        const IElementParameters* pEleBehavior = pickedElement->GetElementParameters();
        if (pEleBehavior)
        {
            ParameterProcessType processType = 
                pEleBehavior->GetParameterById(paramDefinition->GetId())->GetParameterProcessType();
            if (processType == ParameterProcessType::GeneralOutput || processType == ParameterProcessType::Bound)
            {
                pItem->SetEditStyle(esNone);
                pItem->SetEnable(false);
            }
            else
            {
                if (!pEleBehavior->IsParameterModifiable(paramDefinition->GetId()))
                {
                    pItem->SetEditStyle(esNone);
                    pItem->SetEnable(false);
                }
            }
        }

        DisplayParameterInItem(pItem, currentParam, paramDefinition);
    }

    m_pInstaceWidget->RefreshView();
}

CInstancePropertyWidget* EditComponentTypeDlg::CreateInstancePropertyWidget()
{
    int width = m_ui.propertyWidget->width();
    int height = m_ui.propertyWidget->height();

    // 创建PropertyWidget
    OwnerPtr<CPropertyInstanceSetting> opPIS = NEW_AS_OWNER_PTR(CPropertyInstanceSetting);
    CPropertyInstanceSetting* pPropertyInstanceSetting = TRANSFER_OWNERSHIP_TO_THIRD_PARTY(opPIS);
    CInstancePropertyWidget* pInstaceWidget = NEW_AS_QT_CHILD(CInstancePropertyWidget, width, height, pPropertyInstanceSetting, m_ui.propertyWidget);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInstaceWidget != nullptr, L"PropertyWidget创建不成功",L"GDMPLab",L"2024-03-30");
    pInstaceWidget->SetTreePropertyBrowserName(QString::fromStdWString(L"propertyBrowser"));
    QtPropertyEditorView* pPropertyEditorView = pInstaceWidget->GetPropertyEditorView();
    if (nullptr == pPropertyEditorView) return nullptr;
    // 必须对QTreeWidget设置名称，回放日志会通过名称查找这个控件
    pPropertyEditorView->setObjectName(QString::fromStdWString(L"TPD_treeWidget"));
    // 显示表头
    pPropertyEditorView->setHeaderHidden(false);
    pPropertyEditorView->header()->setDefaultAlignment(Qt::AlignCenter);
    pPropertyEditorView->headerItem()->setText(0, QString::fromStdWString(GBMP_TR(L"参数名称")));
    pPropertyEditorView->headerItem()->setText(1, QString::fromStdWString(GBMP_TR(L"值")));

    connect(pInstaceWidget, SIGNAL(PropertyChanged(int, int)), this, SLOT(OnPropertyValueChanged(int, int)), Qt::UniqueConnection);

    return pInstaceWidget;
}

void EditComponentTypeDlg::DisplayParameterInItem(CPropertyItem* pItem, const IParameter *param, const IParameterDefinition *paramDef)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(param, L"Input parameter is null.",L"GDMPLab",L"2024-03-30");
    QString paramDisplayStr = QString::fromStdWString(
        ParameterDisplayUtils::GetValueAsDisplayString(param));
    IParameterDisplayManager* pParamDisplayMgr = IParameterDisplayManager::Get(m_pDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pParamDisplayMgr, L"pParamDisplayMgr为空",L"GDMPLab",L"2024-03-30");
    const IParameterDisplay* paramDisplay = pParamDisplayMgr->GetParameterDisplay(paramDef);
    if(paramDisplay == nullptr) return;

    if (const IParameterDisplayDropdownList * dropdownList = dynamic_cast<const IParameterDisplayDropdownList*>(paramDisplay))
    {
        std::vector<ElementId> elementIds = { m_typeId };
        std::vector<std::wstring> displayStrings = dropdownList->GetDisplayStrings(m_pDoc, elementIds);
        QStringList strList;
        for (auto& str : displayStrings)
        {
            strList << QString::fromStdWString(str);
        }

        pItem->SetEditStyle(esDropDown);
        pItem->SetComboboxItems(strList);
        pItem->SetValue(paramDisplayStr);
    }
    else if (dynamic_cast<const IParameterDisplayEditbox*>(paramDisplay))
    {
        pItem->SetValue(paramDisplayStr);
    }
    else if (dynamic_cast<const IParameterDisplayEditboxWithButton*>(paramDisplay))
    {
        pItem->SetEditStyle(esLineEllipsis);
        pItem->SetValue(paramDisplayStr);
    }
    else if (dynamic_cast<const IParameterDisplayCheckbox *>(paramDisplay))
    {
        pItem->SetEditStyle(esBool);
        pItem->SetValue(param->GetValueAsBool() ? Qt::Checked : Qt::Unchecked);
    }
    else
    {
        DBG_WARN_AND_RETURN_VOID_UNLESS(false, L"未知类型的ParameterDisplay",L"GDMPLab",L"2024-03-30");
    }
}

void EditComponentTypeDlg::UpdatePropertyTableToElement()
{
    IElement* pickedType = m_pDoc->GetElement(m_typeId);
    if (pickedType == nullptr)
        return;

    IElementParameters* pParamBehavior = pickedType->GetElementParameters();
    if (!pParamBehavior)
        return;

    // 更新"名称"参数
    std::wstring strName = m_ui.lineEdit_TypeName->text().toStdWString();
    OwnerPtr<IParameter> nameParameter;
    nameParameter = pParamBehavior->GetParameterByUid(PARAMETER_UID(ElementNameBuiltInParameter));

    IFamilyType* pFamilyType = nullptr;
    if (IInstanceType* instanceType = dynamic_cast<IInstanceType*>(pickedType))
    {
        if (instanceType->IsSub())
        {
            IFamily* pTopFamily = quick_cast<IFamily>(m_pDoc->GetElement(instanceType->GetTopFamilyId()));
            DBG_WARN_AND_RETURN_VOID_UNLESS(pTopFamily, L"获取嵌套构件主构件信息为空",L"GDMPLab",L"2024-03-30");
            pFamilyType=quick_cast<IFamilyType>(pTopFamily->GetSubFamilyTypeBySubInstanceType(instanceType));
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyType, L"获取不到FamilyType",L"GDMPLab",L"2024-03-30");
        }
        else
        {
            IFamily* family = quick_cast<IFamily>(instanceType->GetFamily());
            DBG_WARN_AND_RETURN_VOID_UNLESS(family, L"获取不到Family",L"GDMPLab",L"2024-03-30");
            pFamilyType = quick_cast<IFamilyType>(family->GetFamilyTypeByName(nameParameter->GetValueAsString()));
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyType, L"获取不到FamilyType",L"GDMPLab",L"2024-03-30");

            if (nameParameter->GetValueAsString() != strName)
            {
                // FamilyType的名称也需要修改
                pFamilyType->SetName(strName);
            }
        }
    }
    else if (IGenericType* pGenType = dynamic_cast< IGenericType* >(pickedType))
    {
    }
    else if (IDrawingViewportType* pDrawingViewportType = quick_cast<IDrawingViewportType>(pickedType))
    {
        IElementBasicInformation* pBasicInformation = pickedType->GetBasicInformation();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pBasicInformation, L"pBasicInformation不应该为空",L"GDMPLab",L"2024-03-30");
        pBasicInformation->SetName(strName);
    }
    else
    {
        DBG_WARN_AND_RETURN_VOID_UNLESS(false, L"请添加相应的类型处理",L"GDMPLab",L"2024-03-30");
    }

    if (nameParameter->GetValueAsString() != strName)
    {
        nameParameter->SetValueAsString(strName);
        IElementParameters* pParameters = pickedType->GetElementParameters();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pParameters, L"pParameters为空",L"GDMPLab",L"2024-03-30");
        pParameters->SetParameter(nameParameter.get());
    }

    // 更新参数列表
    std::wstring strDefaultGroup = GBMP_TR(L"基本属性");
    std::wstring strUndefinedGroup = GBMP_TR(L"参数列表");      // 未分组的参数放在这个组下
    const IParameterGroupsFilter* pGroupsFilter = IParameterGroupsFilter::GetParameterGroupsFilter();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pGroupsFilter != nullptr, L"pGroupsFilter为空",L"GDMPLab",L"2024-03-30");
    for (int loop = 0; loop < (int)m_vecDisplayedParameters.size(); ++loop)
    {
        IParameter* currentParam = m_vecDisplayedParameters.at(m_vecParametersOrder.at(loop)).get();
        DBG_WARN_AND_CONTINUE_UNLESS(currentParam, L"currentParam为空",L"GDMPLab",L"2024-03-30");
        if (!currentParam->IsUserVisible())
        {
            continue;
        }
        const IParameterDefinition* currentParamDef = currentParam->GetParameterDefinition();
        DBG_WARN_AND_CONTINUE_UNLESS(currentParamDef, L"currentParamDef为空",L"GDMPLab",L"2024-03-30");

        std::wstring groupName = pGroupsFilter->GetGroupName(currentParamDef);
        if (groupName == strDefaultGroup) groupName = strUndefinedGroup;
        CPropertyGroupItem* pGroupItem = m_pInstaceWidget->GetPropertyGroupByName(QString::fromStdWString(groupName));
        if (nullptr == pGroupItem) continue;

        CPropertyItem* pItem = pGroupItem->GetItem(currentParamDef->GetId());
        if (pItem)
        {
            QString strParamName = pItem->GetName();
            QString strInternalParamName = QString::fromStdWString(currentParamDef->GetName());
            DBG_WARN_AND_CONTINUE_UNLESS(strParamName.compare(strInternalParamName) == 0, L"参数名不匹配",L"GDMPLab",L"2024-03-30");
        }

        UpdateElementParameters(pItem, pickedType, currentParam);

        // Type类型中，修改了类型参数，需要同时修改FamilyType中的参数值
        if (pFamilyType)
        {
            const std::vector<OwnerPtr<IParameter>>& familyParameters = pFamilyType->GetFamilyParameters();
            auto findIter = std::find_if(familyParameters.begin(), familyParameters.end(), [&](const OwnerPtr<IParameter>& parameter) {return parameter->GetParameterDefinitionUid() == currentParam->GetParameterDefinitionUid(); });
            if (findIter != familyParameters.end())
            {
                OwnerPtr<IParameter> familyParameter = (*findIter)->Clone();
                DBG_WARN_AND_CONTINUE_UNLESS(familyParameter, L"familyParameter为空",L"GDMPLab",L"2024-03-30");

                const IParameterValueStorage* pParameterValue = currentParam->GetParameterValueStorage();
                DBG_WARN_AND_CONTINUE_UNLESS(pParameterValue, L"pParameterValue为空",L"GDMPLab",L"2024-03-30");

                familyParameter->SetParameterValueStorage(TransferOwnership(pParameterValue->Clone()));
                pFamilyType->SetFamilyParameter(m_pDoc, familyParameter.get());
            }
        }
    }
}

void EditComponentTypeDlg::UpdateElementParameters(CPropertyItem* pItem, IElement*  element, IParameter* param)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(param, L"Input parameter is null.",L"GDMPLab",L"2024-03-30");
    const IParameterDefinition* currentParamDef = param->GetParameterDefinition();
    DBG_WARN_AND_RETURN_VOID_UNLESS(currentParamDef, L"ParameterDefinition获取不到",L"GDMPLab",L"2024-03-30");
    IParameterDisplayManager* pParamDisplayMgr = IParameterDisplayManager::Get(m_pDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pParamDisplayMgr, L"pParamDisplayMgr为空",L"GDMPLab",L"2024-03-30");
    const IParameterDisplay* paramDisplay = pParamDisplayMgr->GetParameterDisplay(currentParamDef);
    if (const IParameterDisplayDropdownList* dropdownList = dynamic_cast<const IParameterDisplayDropdownList*>(paramDisplay))
    {
        QString strCurValue = pItem->GetValue().toString();
        std::vector<ElementId> ids = { m_typeId };
        OwnerPtr<IParameterValueStorage> pvs = dropdownList->GetValueByDisplayString(m_pDoc, strCurValue.toStdWString(), ids);
        if (pvs)
        {
            const IParameterValueStorage* paramValue = param->GetParameterValueStorage();
            if (paramValue && !paramValue->HasSameValue(pvs.get()))
            {
                param->SetParameterValueStorage(TransferOwnership(pvs));
                element->GetElementParameters()->SetParameter(param);
            }
        }
        else
        {
            if (strCurValue.compare(QString::fromStdWString(L"更多材质")) == 0)
            {
                ElementId materialId;
                UiCommonDialog::ShowMaterialSelectionDialog(m_pDoc, materialId);
                if (!materialId.IsValid())
                {
                    return;
                }

                IGraphicsMaterial* pMaterialElement = quick_cast<IGraphicsMaterial>(m_pDoc->GetElement(materialId));
                if (pMaterialElement == nullptr)
                {
                    UiCommonDialog::ShowMessageBox(GBMP_TR(L"发生错误"), GBMP_TR(L"材质创建失败！"), (int)UiCommonDialog::ButtonType::OK);
                    return;
                }
                param->SetValueAsElementId(materialId);
                element->GetElementParameters()->SetParameter(param);
            }
        }
    }
    else if (dynamic_cast<const IParameterDisplayEditbox*>(paramDisplay) || dynamic_cast<const IParameterDisplayEditboxWithButton*>(paramDisplay))
    {
        QString strValue = pItem->GetValue().toString();
        // 滤除后缀
        if (currentParamDef->GetParameterTypeId() == PARAMETER_TYPE(Length))
        {
            strValue = strValue.left(strValue.indexOf(' '));
        }

        const std::wstring& displayStr = ParameterDisplayUtils::GetValueAsDisplayString(param);
        if (displayStr != strValue.toStdWString() && !strValue.isEmpty())
        {
            bool isSuccess = ParameterDisplayUtils::SetValueFromDisplayString(param, 
                strValue.toStdWString());
            if (isSuccess)
            {
                std::wstring errorMsg;
                if (element->GetElementParameters() && 
                    !element->GetElementParameters()->SetParameter(param, 
                        &errorMsg) || errorMsg.size())
                {
                    UiCommonDialog::ShowMessageBox(GBMP_TR(L"发生错误"), errorMsg, (int)UiCommonDialog::ButtonType::OK);
                    pItem->SetValue(QString::fromStdWString(displayStr));
                    return;
                }
            }
        }
    }
    else if (dynamic_cast<const IParameterDisplayCheckbox*>(paramDisplay))
    {
        bool boolCurValue = pItem->GetValue().toBool();
        if (param->GetValueAsBool() != boolCurValue)
        {
            param->SetValueAsBool(boolCurValue);
            if(element->GetElementParameters())
                element->GetElementParameters()->SetParameter(param);
        }
    }
    else
    {
        DBG_WARN_AND_RETURN_VOID_UNLESS(false, L"未知类型的ParameterDisplay",L"GDMPLab",L"2024-03-30");
    }

}
